import {
  $configuration, iAiConfiguration, iAiHistory, iChatBoxHandleMessage, iChatBoxHistory, Scroll,
  Input,
  i18n,
  Button,
  $ai,
  $message, Alert, Box,
} from "plain-design";
import {iAiChatStreamParameter} from "./chatStream";
import {ReactNode, useMemo, useRef, useState} from "react";
import {getComponentCls} from "@peryl/react-compose";
import {classnames} from '@peryl/utils/classnames';
import {createEffects} from "@peryl/utils/createEffects";
import {delay} from "@peryl/utils/delay";
import {uuid} from "@peryl/utils/uuid";
import {lastItem} from "@peryl/utils/lastItem";
import {toArray} from "@peryl/utils/toArray";
import {doNothing} from "@peryl/utils/doNothing";

export const ReactChatBox = (
  props: {
    /*ai配置信息*/
    aiConfig?: iAiConfiguration,
    /*填充高度*/
    fitHeight?: boolean,
    /*已有的对话历史信息*/
    histories?: iChatBoxHistory[],
    /*系统提示词*/
    systemContent?: string,
    /*用户输入的内容*/
    userContent?: string,
    /*手动处理大模型返回的message*/
    handleMessage?: iChatBoxHandleMessage,
    handleReceive?: (data: { fullText?: string, chunkText?: string }) => void,
    beforeSendUserContent?: (data: { userContent: string, messages: iAiHistory[] }) => Promise<void>,
    handleChatStream?: (parameter: iAiChatStreamParameter & { userContent: string }) => Promise<any>,
    inputMinHeight?: string,
    inputMaxHeight?: string,
    enableMemory?: boolean,
    // 启用内存
    memoryLimit?: number,
    // 内存限制
    slotsPrepend?: ReactNode,
    // 插槽预置
  }
) => {
  const aiConfig = props.aiConfig ?? $configuration.get('aiConfig');
  const fitHeight = props.fitHeight ?? false;
  const inputMinHeight = props.inputMinHeight ?? '80px';
  const inputMaxHeight = props.inputMaxHeight ?? '225px';
  const enableMemory = props.enableMemory ?? false;
  const memoryLimit = props.memoryLimit ?? 15;

  const scrollRef = useRef<null | typeof Scroll.use.class>(null);

  const classes = useMemo(() => {
    return classnames([
      getComponentCls('ai-chat-box'),
      // `ai-chat-box-size-${styleComputed.value.size}`,
      `ai-chat-box-size-normal`,
      {
        'ai-chat-box-fit-height': fitHeight
      }
    ]);
  }, [fitHeight]);

  const [histories, setHistories] = useState<iChatBoxHistory[]>([]);
  const [loading, setLoading] = useState(false);
  const [userContent, setUserContent] = useState(props.userContent);

  const [abortEffects] = useState(() => createEffects().effects);

  const methods = {
    scrollEnd: async () => {
      if (!!scrollRef.current) {
        await delay(78);
        scrollRef.current.methods.scrollEnd();
      }
    },
    addHistory: async (...history: iChatBoxHistory[]) => {
      setHistories([...histories, ...history]);
      await methods.scrollEnd();
    },
    send: async (userContent: string) => {
      // debugger
      setUserContent('');
      await delay(0);
      const newUserHistory: iChatBoxHistory = { role: 'user', content: userContent, id: uuid() };
      histories.push(newUserHistory);
      setHistories([...histories]);

      /*const { message, chatData } = await $ai.chatSystem(userContent, props.systemContent, aiConfig);*/
      let messages: iAiHistory[] = enableMemory ? histories : (() => {
        const { role, content } = newUserHistory;
        return [{ role, content }];
      })();
      messages = messages.slice(memoryLimit * -1);
      await props.beforeSendUserContent?.({ userContent, messages });
      if (!!props.systemContent?.trim().length) {messages.unshift({ role: 'system', content: props.systemContent });}
      let chatBoxHistory: iChatBoxHistory = {
        id: uuid(),
        role: 'assistant',
        content: '',
      };
      let message = '';
      histories.push(chatBoxHistory);
      setHistories([...histories]);

      const aiChatStreamParameter: iAiChatStreamParameter & { userContent: string } = {
        aiConfig,
        messages,
        userContent,
        abortEffects,
        onReceiving: ({ fullText, chunkText }) => {
          // console.log('receiving', fullText);
          props.handleReceive?.({ fullText, chunkText });
          const findIndex = histories.findIndex(i => i.id === chatBoxHistory.id);
          if (findIndex === -1) {
            console.error('程序异常！');
          } else {
            chatBoxHistory.content = fullText;
            histories[findIndex] = { ...chatBoxHistory };
            setHistories([...histories]);
            methods.scrollEnd();
          }
        },
        onFinish: (fullText) => {
          message = fullText;
        },
      };

      if (!!props.handleChatStream) {
        await props.handleChatStream(aiChatStreamParameter);
      } else {
        await $ai.chatStream(aiChatStreamParameter);
      }

      if (!message.length) {
        throw new Error('message is empty!');
      }

      /*可以手动处理返回的消息，自定义往对话框插入内容*/
      await props.handleMessage?.({
        message,
        userContent,
        // chatData,
        histories: histories,
        scrollEnd: methods.scrollEnd,
        // 这里react版本不实现这个函数
        addHistory: doNothing as any,
      });

      return { message, /*chatData*/ };
    },
  };

  const handler = {
    onClickSend: async () => {
      if (loading) {
        console.log('abort');
        abortEffects.clear();
        return;
      }

      console.log('send');
      abortEffects.clear();
      abortEffects.push(() => {setLoading(false);});
      setLoading(true);
      try {
        if (!userContent?.trim().length) {
          $message.error(i18n.$it('ai.require').d('提问的内容不能为空'));
          return;
        }
        await methods.send(userContent);
      } finally {
        setLoading(false);
      }
    },
    onEnterTextarea: (e: KeyboardEvent) => {
      if (e.shiftKey) {return;}
      handler.onClickSend();
    },
  };


  return (
    <div className={classes}>
      <Box className="mb">
        <Alert label="This is react chat box."/>
      </Box>
      {!!props.slotsPrepend && (
        <div className="ai-chat-box-history-prepend">
          {props.slotsPrepend}
        </div>
      )}
      {(!!histories.length || fitHeight || !!props.slotsPrepend) && (
        <div className="ai-chat-box-histories">
          {(() => {
            const content = histories.map((history) => (
              <div className="ai-chat-box-history-item" key={history.id} data-role={history.role}>
                <div className="ai-chat-box-history-item-inner">
                  {!!history.render ? history.render() : history.content}
                </div>
              </div>
            ));

            // if (fitHeight) {
            //   return <Scroll ref={scrollRef}>{content}</Scroll>;
            // } else {
            //   return content;
            // }
            return <Scroll ref={scrollRef}>{content}</Scroll>;
          })()}
        </div>
      )}
      <div className="ai-chat-box-input">
        <Input
          readonly={loading}
          textarea
          modelValue={userContent}
          onUpdateModelValue={val => setUserContent(val)}
          // placeholder={props.placeholder || i18n.$it('ai.placeholder').d('请输入要发送给ai的内容如：你是谁')}
          placeholder={i18n.$it('ai.placeholder').d('请输入要发送给ai的内容如：你是谁')}
          minHeight={inputMinHeight}
          maxHeight={inputMaxHeight}
          onEnter={handler.onEnterTextarea}
        />
        <Button shape="round" mode="fill" icon={loading ? 'ie-stop' : 'ie-send'} className="ai-chat-box-send-button" onClick={handler.onClickSend}/>
      </div>
    </div>
  );
};
